home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / sockuser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  8.2 KB  |  416 lines

  1. #include "global.h"
  2. #ifdef    ANSIPROTO
  3. #include <stdarg.h>
  4. #endif
  5. #include "mbuf.h"
  6. #include "proc.h"
  7. #include "socket.h"
  8. #include "usock.h"
  9. #include "session.h"
  10. #include "nr4.h"
  11.  
  12. static int rrecvchar __ARGS((struct usock *up,int s));
  13.  
  14. /* Higher-level receive routine, intended for connection-oriented sockets.
  15.  * Can be used with datagram sockets, although the sender id is lost.
  16.  */
  17. int recv(s,buf,len,flags)
  18. int s;        /* Socket index */
  19. char *buf;    /* User buffer */
  20. int len;    /* Max length to receive */
  21. int flags;    /* Unused; will eventually select oob data, etc */
  22. {
  23.     struct mbuf *bp;
  24.     int cnt;
  25.  
  26.     if(len == 0)
  27.         return 0;    /* Otherwise would be interp as "all" */
  28.  
  29.     cnt = recv_mbuf(s,&bp,flags,NULLCHAR,(int *)NULL);
  30.     if(cnt > 0){
  31.         cnt = min(cnt,len);
  32.         pullup(&bp,buf,(int16)cnt);
  33.         free_p(bp);
  34.     }
  35.     return cnt;
  36. }
  37.  
  38. /* Higher level receive routine, intended for datagram sockets. Can also
  39.  * be used for connection-oriented sockets, although from and fromlen are
  40.  * ignored.
  41.  */
  42. int recvfrom(s,buf,len,flags,from,fromlen)
  43. int s;        /* Socket index */
  44. char *buf;    /* User buffer */
  45. int len;    /* Maximum length */
  46. int flags;    /* Unused; will eventually select oob data, etc */
  47. char *from;    /* Source address, only for datagrams */
  48. int *fromlen;    /* Length of source address */
  49. {
  50.     struct mbuf *bp;
  51.     register int cnt;
  52.  
  53.     cnt = recv_mbuf(s,&bp,flags,from,fromlen);
  54.     if(cnt > 0){
  55.         cnt = min(cnt,len);
  56.         pullup(&bp,buf,(int16)cnt);
  57.         free_p(bp);
  58.     }
  59.     return cnt;
  60. }
  61.  
  62. /* High level send routine */
  63. int send(s,buf,len,flags)
  64. int s;        /* Socket index */
  65. char *buf;    /* User buffer */
  66. int len;    /* Length of buffer */
  67. int flags;    /* Unused; will eventually select oob data, etc */
  68. {
  69.     register struct mbuf *bp;
  70.     char sock[MAXSOCKSIZE];
  71.     int i = MAXSOCKSIZE;
  72.  
  73.     if(getpeername(s,sock,&i) == -1)
  74.         return -1;
  75.     bp = qdata(buf,(int16)len);
  76.     return send_mbuf(s,bp,flags,sock,i);
  77. }
  78.  
  79. /* High level send routine, intended for datagram sockets. Can be used on
  80.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  81.  */
  82. int sendto(s,buf,len,flags,to,tolen)
  83. int s;        /* Socket index */
  84. char *buf;    /* User buffer */
  85. int len;    /* Length of buffer */
  86. int flags;    /* Unused; will eventually select oob data, etc */
  87. char *to;    /* Destination, only for datagrams */
  88. int tolen;    /* Length of destination */
  89. {
  90.     register struct mbuf *bp;
  91.  
  92.     bp = qdata(buf,(int16)len);
  93.     return send_mbuf(s,bp,flags,to,tolen);
  94. }
  95.  
  96. /* Receive a newline-terminated line from a socket, returning # chars read.
  97.  * The end-of-line sequence is recognized and translated into a single '\n'.
  98.  */
  99. int recvline(s,buf,len)
  100. int s;        /* Socket index */
  101. char *buf;    /* User buffer */
  102. unsigned len;    /* Length of buffer */
  103. {
  104.     int c;
  105.     int cnt = 0;
  106.  
  107.     while(len-- > 1){
  108.         if((c = recvchar(s)) == EOF){
  109.             cnt = -1;
  110.             break;
  111.         }
  112.         if(buf != NULLCHAR)
  113.             *buf++ = c;
  114.         cnt++;
  115.         if(uchar(c) == '\n')
  116.             break;
  117.     }
  118.     if(buf != NULLCHAR)
  119.         *buf = '\0';
  120.     return cnt;
  121. }
  122.  
  123. #if    defined(ANSIPROTO)
  124. /* Do printf on a user socket */
  125. int usprintf(int s,char *fmt,...)
  126. {
  127.     va_list args;
  128.     int len;
  129.  
  130.     va_start(args,fmt);
  131.     len = usvprintf(s,fmt,args);
  132.     va_end(args);
  133.     return len;
  134. }
  135.  
  136. /* Printf on standard output socket */
  137. int tprintf(char *fmt,...)
  138. {
  139.     va_list args;
  140.     int len;
  141.  
  142.     va_start(args,fmt);
  143.     len = usvprintf(Curproc->output,fmt,args);
  144.     va_end(args);
  145.     return len;
  146. }
  147.  
  148. /* The guts of printf, uses variable arg version of sprintf */
  149. int usvprintf(int s,char *fmt, va_list args)
  150. {
  151.     int len,withargs;
  152.     register int i;
  153.     char *buf;
  154.     register char *cp;
  155.  
  156.     if(strchr(fmt,'%') == NULLCHAR){
  157.         /* No args, so we don't need vsprintf() */
  158.         withargs = 0;
  159.         buf = fmt;
  160.         len = strlen(fmt);
  161.     } else {
  162.         /* Use a default value that is hopefully longer than the
  163.          * biggest output string we'll ever print (!)
  164.          */
  165.         withargs = 1;
  166.         buf = mallocw(SOBUF);
  167.         vsprintf(buf,fmt,args);
  168.         len = strlen(buf);
  169.     }
  170.     cp = buf;
  171.     i = len;
  172.     while(i-- > 0)
  173.         usputc(s,*cp++);
  174.     if(withargs)
  175.         free(buf);
  176.     return len;
  177. }
  178. #else
  179. /*VARARGS*/
  180.  
  181. /* Printf to standard output socket */
  182. int tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  183. char *fmt;        /* Message format */
  184. int arg1,arg2,arg3;    /* Arguments */
  185. int arg4,arg5,arg6;
  186. int arg7,arg8,arg9;
  187. int arg10,arg11,arg12;
  188. {
  189.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6
  190.         arg7,arg8,arg9,arg10,arg11,arg12);
  191. }
  192.  
  193. /* Printf to socket. Doesn't use ANSI vsprintf */
  194. int usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  195. int s;            /* Socket index */
  196. char *fmt;        /* Message format */
  197. int arg1,arg2,arg3;    /* Arguments */
  198. int arg4,arg5,arg6;
  199. int arg7,arg8,arg9;
  200. int arg10,arg11,arg12;
  201. {
  202.     int len,withargs;
  203.     register int i;
  204.     char *buf;
  205.     register char *cp;
  206.  
  207.     if(strchr(fmt,'%') == NULLCHAR){
  208.         /* No args, so we don't need vsprintf() */
  209.         withargs = 0;
  210.         buf = fmt;
  211.         len = strlen(fmt);
  212.     } else {
  213.         /* Use a default value that is hopefully longer than the
  214.          * biggest output string we'll ever print (!)
  215.          */
  216.         withargs = 1;
  217.         buf = mallocw(SOBUF);
  218.         sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7
  219.          arg8,arg9,arg10,arg11,arg12);
  220.         len = strlen(buf);
  221.     }
  222.     cp = buf;
  223.     i = len;
  224.     while(i-- > 0)
  225.         usputc(s,*cp++);
  226.     if(withargs)
  227.         free(buf);
  228.     return len;
  229. }
  230. #endif
  231.  
  232. /* Buffered putchar to a socket */
  233. int usputc(s,c)
  234. int s;
  235. char c;
  236. {
  237.     struct usock *up;
  238.     register struct mbuf *bp;
  239.     char *cp;
  240.  
  241.     if((up = itop(s)) == NULLUSOCK){
  242.         errno = EBADF;
  243.         return -1;
  244.     }
  245.     if(up->obuf == NULLBUF){
  246.         /* Allocate a buffer of appropriate size */
  247.         switch(up->type){
  248.         case TYPE_NETROML4:
  249.             up->obuf = alloc_mbuf(NR4MAXINFO);
  250.             break;
  251.         default:
  252.             up->obuf = alloc_mbuf(BUFSIZ);
  253.             break;
  254.         }
  255.     }
  256.     bp = up->obuf;
  257.     if(c == '\n' && up->eol[0] != '\0'){
  258.         /* Translate into appropriate end-of-line sequence */
  259.         for(cp = up->eol;*cp != '\0';cp++)
  260.             bp->data[bp->cnt++] = *cp;
  261.     } else {
  262.         bp->data[bp->cnt++] = c;
  263.     }
  264.     if((c == up->flush && up->flush != -1) || bp->cnt >= bp->size-2)
  265.         usflush(s);
  266.  
  267.     return (int)uchar(c);
  268. }
  269.  
  270. /* Put a character to standard output socket */
  271. int tputc(c)
  272. char c;
  273. {
  274.     return usputc(Curproc->output,c);
  275. }
  276.  
  277. int usputs(s,x)
  278. int s;
  279. register char *x;
  280. {
  281.     while(*x != '\0')
  282.         if(usputc(s,*x++) == EOF)
  283.             return EOF;
  284.     return 0;
  285. }
  286.  
  287. /* Put a string to standard output socket */
  288. int tputs(s)
  289. char *s;
  290. {
  291.     return usputs(Curproc->output,s);
  292. }
  293.  
  294. /* Read a raw character from a socket with stream buffering. */
  295. static int rrecvchar(up,s)
  296. register struct usock *up;
  297. int s;            /* Socket index */
  298. {
  299.     char c;
  300.  
  301.     /* Replenish if necessary */
  302.     if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0)
  303.         return EOF;
  304.  
  305.     if(pullup(&up->ibuf,&c,1) == 1)
  306.         return (int)uchar(c);
  307.     else
  308.         return EOF;
  309. }
  310.  
  311. /* This function recognizes the end-of-line sequence for the stream
  312.  * and translates it into a single '\n'.
  313.  */
  314. int recvchar(s)
  315. int s;            /* Socket index */
  316. {
  317.     int c;
  318.     register struct usock *up;
  319.  
  320.     if((up = itop(s)) == NULLUSOCK)
  321.         return EOF;
  322.  
  323.     c = rrecvchar(up,s);
  324.  
  325.     if(c != up->eol[0] || up->eol[0] == '\0')
  326.         return (int)c;
  327.  
  328.     /* This is the first char of a eol sequence. If the eol sequence is
  329.      * more than one char long, eat the next character in the input stream.
  330.      */
  331.     if(up->eol[1] != '\0'){
  332.         (void)rrecvchar(up,s);
  333.     }
  334.     return '\n';
  335. }
  336.  
  337. /* Flush output on a socket stream */
  338. void usflush(s)
  339. int s;
  340. {
  341.     register struct usock *up;
  342.     struct mbuf *bp;
  343.  
  344.     if((up = itop(s)) == NULLUSOCK)
  345.         return;
  346.  
  347.     if(up->obuf != NULLBUF){
  348.         bp = up->obuf;
  349.         up->obuf = NULLBUF;
  350.         send_mbuf(s,bp,0,NULLCHAR,0);
  351.     }
  352. }
  353.  
  354. /* Flush output socket */
  355. void tflush()
  356. {
  357.     usflush(Current->output);
  358. }
  359.  
  360. /* Print prompt and read one character */
  361. int keywait(prompt,flush)
  362. char *prompt;    /* Optional prompt */
  363. int flush;    /* Flush queued input? */
  364. {
  365.     int c;
  366.  
  367.     if(flush && socklen(Curproc->input,1) != 0)
  368.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  369.     if(prompt != NULLCHAR)
  370.         tprintf(prompt);
  371.     else
  372.         tprintf("Hit enter to continue");
  373.     tflush();
  374.     if((c = recvchar(Curproc->input)) == EOF)
  375.         return -1;
  376.     tprintf("\r%75s\r"," ");
  377.     tflush();
  378.     return (int)c;
  379. }
  380.  
  381. /* Set the end-of-line sequence on a socket */
  382. int seteol(s,seq)
  383. int s;
  384. char *seq;
  385. {
  386.     register struct usock *up;
  387.  
  388.     if((up = itop(s)) == NULLUSOCK)
  389.         return -1;
  390.  
  391.     if(seq != NULLCHAR)
  392.         strncpy(up->eol,seq,sizeof(up->eol));
  393.     else
  394.         *up->eol = '\0';
  395.     return 0;
  396. }
  397.  
  398. /* Specify the character to trigger automatic output buffer
  399.  * flushing, or -1 to disable it
  400.  */
  401. int setflush(s,c)
  402. int s;
  403. int c;
  404. {
  405.     register struct usock *up;
  406.     int old;
  407.  
  408.     if((up = itop(s)) == NULLUSOCK)
  409.         return -1;
  410.  
  411.     old = up->flush;
  412.     up->flush = c;
  413.     return old;
  414. }
  415.  
  416.